package com.base.cn.platform.os.controller.order.pay;

import com.base.cn.platform.os.common.constants.ConfigName;
import com.base.cn.platform.os.common.j2cache.CustomCacheChannel;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.order.OrderSource;
import com.base.cn.platform.os.common.utils.order.OrderStatus;
import com.base.cn.platform.os.common.utils.order.PayType;
import com.base.cn.platform.os.common.utils.pay.AlipayUtils;
import com.base.cn.platform.os.common.utils.pay.PayFormClient;
import com.base.cn.platform.os.common.utils.pay.PayService;
import com.base.cn.platform.os.common.utils.pay.WeiXinUtils;
import com.base.cn.platform.os.common.utils.pay.config.PlayCallbackParams;
import com.base.cn.platform.os.common.utils.result.ResultUtil;
import com.base.cn.platform.os.controller.cmmon.ApiBaseController;
import com.base.cn.platform.os.entity.order.order.OrderType;
import com.base.cn.platform.os.service.manage.config.SysConfigService;
import com.base.cn.platform.os.service.manage.order.goods.OrderService;
import com.base.cn.platform.os.service.manage.order.pay.PayOrderCallbackService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * 支付接口Controller
 *
 * @author s.li
 * @create 2018-09-18-15:38
 */
@RestController
@RequestMapping("/api/pay")
@Slf4j
public class ApiPayController extends ApiBaseController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private PayOrderCallbackService payOrderCallbackService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private CustomCacheChannel customCacheChannel;

    /**
     * 获取支付数据  (用于安卓、小程序)
     * @param request HttpServletRequest
     * @param userId 用户ID
     * @param shopData 商品数据
     * @param orderNo 订单号
     * @param orderType 订单类型
     * @param payType 支付类型
     * @param code 微信小程序code
     * @param payFormClient 支付来源类型
     * @return  Map<String,Object>
     */
    @RequestMapping("/gotoPay")
    public Map<String,Object> gotoPay(HttpServletRequest request,
                                      @RequestParam("userId") BigDecimal userId,
                                      @RequestParam(value = "shopData",required = false) String shopData,
                                      @RequestParam("orderNo") String orderNo,
                                      @RequestParam("orderType") String orderType,
                                      @RequestParam("payType") String payType,
                                      @RequestParam(value = "code",required = false) String code,
                                      @RequestParam("payFormClient") String payFormClient) throws Exception{
        double accountPrice = 0D;
        if(orderType.equals(OrderType.ACCOUNT.getKey())){
            accountPrice = Double.parseDouble(shopData.split("-")[2]);
        }
        Map<String,Object> _res = orderService.checkWebOrderData(userId,orderNo,orderType,payType,accountPrice);
        if(!ResultUtil.getSuccess(_res)){//如果订单验证失败
            return _res;
        }
        if (!payType.equals(PayType.PAY_TYPE_WEIXIN) && !payType.equals(PayType.PAY_TYPE_ALIPAY) && !payType.equals(PayType.PAY_TYPE_ACCOUNT) && payType.equals(PayType.PAY_TYPE_IOS)) {
            return ResultUtil.ERROR("该支付接口只支持微信、支付宝、账户类型、IOS内购的支付");
        }
        if ((orderType.equals(OrderType.ACCOUNT.getKey()) && payType.equals(PayType.PAY_TYPE_ACCOUNT)) || (orderType.equals(OrderType.ACCOUNT.getKey()) && payType.equals(PayType.PAY_TYPE_IOS))) {
            return ResultUtil.ERROR( "账户充值不能使用账户类型支付");
        }
        Map<String,Object> order = (Map<String,Object>)ResultUtil.getEntity(_res);
        boolean status = false;
        //普通订单
        if (orderType.equals(OrderType.COMMON.getKey())) {
            //如果未支付成功
            if (order.get("orderStatus").toString().equals(OrderStatus.INIT)) {
                //如果是账户支付类型
                if (payType.equals(PayType.PAY_TYPE_ACCOUNT)) {
                    Map<String,Object> payCallback = PlayCallbackParams.getPayCallbackParams(PayType.PAY_TYPE_ACCOUNT,
                            OrderType.COMMON.getKey(),orderNo,null,userId,"0", payFormClient);
                    Map<String,Object> resultMap = payOrderCallbackService.payCallback(payCallback);
                    return resultMap;
                }
                status = true;
            }
        }
        if(orderType.equals(OrderType.ACCOUNT.getKey())){
            status = true;
        }
        if(status){
            TreeMap<String,String> payConfigMap = sysConfigService.getSysConfigContext(ConfigName.PAY);
            PayService payService;
            Map<String,String> params = new HashMap<>();
            params.put("orderNo",orderNo);
            params.put("userId",String.valueOf(userId));
            params.put("totalAmount",order.get("realPrice").toString());
            params.put("describe",order.get("shopNames").toString());
            String url = request.getRequestURL().toString();
            String contextUrl = url.split("/api/pay/gotoPay")[0];
            //异步回调路径
            params.put("notifyUrl", contextUrl + "/api/pay/paySuccessCallback/"+payType+"/"+orderType+"/"+orderNo+"/"+userId+"/"+payFormClient);
            //支付宝支付
            if(payType.equals(PayType.PAY_TYPE_ALIPAY)){
                payService = new AlipayUtils();
                Map<String,Object> resultMap = payService.goToPay(request,payConfigMap,params, payFormClient);
                if(ResultUtil.getSuccess(resultMap)){
                    resultMap.put("orderInfo",ResultUtil.getEntity(resultMap));
                    ResultUtil.removeEntity(resultMap);
                }
                return resultMap;
            }
            if(payType.equals(PayType.PAY_TYPE_WEIXIN)){
                payService = new WeiXinUtils();
                if(payFormClient.equals(PayFormClient.APPLY)){
                    String openId = payService.weiXinOpenId(payConfigMap,payConfigMap.get("applyAppId"),payConfigMap.get("applyAppSecret"),PayFormClient.APPLY,code);
                    payConfigMap.put("openid",openId);
                }
                Map<String,Object> resultMap = payService.goToPay(request,payConfigMap,params, payFormClient);
                if(ResultUtil.getSuccess(resultMap)){
                    resultMap.put("weixinInfo",ResultUtil.getEntity(resultMap));
                    ResultUtil.removeEntity(resultMap);
                }
                return resultMap;
            }
        }
        return ResultUtil.ERROR("数据错误，生成支付数据失败");
    }

    /**
     * 支付回调（用于支付宝、微信类型的支付）
     * @param request HttpServletRequest
     * @param response HttpServletResponse
     * @param payType 支付类型
     * @param orderType 订单类型
     * @param orderNo 订单号
     * @param userId 用户ID
     * @param payFormClient 支付来源类型
     * @throws Exception
     */
    @RequestMapping("/paySuccessCallback/{payType}/{orderType}/{orderNo}/{userId}/{payFormClient}")
    public void paySuccessCallback(HttpServletRequest request, HttpServletResponse response,
                                   @PathVariable String payType,
                                   @PathVariable String orderType,
                                   @PathVariable String orderNo,
                                   @PathVariable BigDecimal userId,
                                   @PathVariable String payFormClient) throws Exception{
        log.info("=========================================App支付回调，开始===========");
        PayService payService = null;
        Map<String,String> resultMap = null;
        TreeMap<String,String> payConfigMap = sysConfigService.getSysConfigContext(ConfigName.PAY);
        if(payType.equals(PayType.PAY_TYPE_ALIPAY)){//支付宝支付
            payService = new AlipayUtils();
        }
        if(payType.equals(PayType.PAY_TYPE_WEIXIN)){//微信支付
            payService = new WeiXinUtils();
        }
        if(payService!=null){
            //支付验证
            resultMap = payService.payCallback(request,response,payConfigMap,payFormClient);
        }
        log.info("========================resultMap:"+resultMap);
        //支付验证成功
        if(ObjectUtils.isNotEmpty(resultMap) && resultMap.get("success").equals("true")){
            //修改支付订单
            Map<String,Object> payCallback = PlayCallbackParams.getPayCallbackParams(payType,orderType,orderNo,resultMap.get("treadNo"),userId,resultMap.get("amount"),payFormClient);
            log.info("====================payCallback:"+payCallback);
            Map<String,Object> result = payOrderCallbackService.payCallback(payCallback);
            logger.info("===================result:"+result.toString());
        }
    }

    /**
     * IOS内购支付回调
     * @param userId 用户ID
     * @param orderNo 订单号
     * @param receipt IOS内购（验证凭证，用于订单IOS内购是否真正支付成功）
     * @param price 订单金额
         * @param    type 1充值内购 2 会员内购
     * @return Map<String,Object>
     */
    @RequestMapping("/iosPaySuccess")
    public Map<String,Object> iosPaySuccess(@RequestParam("userId") BigDecimal userId,
                                            @RequestParam("orderNo") String orderNo,
                                            @RequestParam("receipt") String receipt,
                                            @RequestParam("price") double price,
                                            @RequestParam("type") int type){
        try {
            receipt = URLDecoder.decode(receipt,"utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        logger.info("----------------------receipt Str:"+receipt);
        Map<String, Object> result = IOSVerify.buyAppVerify(receipt,customCacheChannel);
        boolean success = ResultUtil.getSuccess(result);
        if(!success){
            return result;
        }
        String externalOrderNo = (String)ResultUtil.getEntity(result);
        //修改支付订单
        Map<String,Object> payCallback = PlayCallbackParams.getPayCallbackParams(PayType.PAY_TYPE_IOS,type==1?OrderType.ACCOUNT.getKey():OrderType.COMMON.getKey(),orderNo,externalOrderNo,userId,String.valueOf(price),OrderSource.ORDER_FORM_IOS);
        result = payOrderCallbackService.payCallback(payCallback);
        return result;

    }

}
